package com.wsz.user.config;

import com.wsz.filter.CustomAuthenticationFilter;
import com.wsz.filter.CustomAuthorizationFilter;
import com.wsz.user.service.impl.UserDetailsServerImpl;
import com.wsz.utils.RedisOperator;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsServer;//数据源
    private final RedisOperator redisOperator;//包装的redis工具类


    //暴露认证管理器
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


    //设置认证管理器的数据源
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServer);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/vc.jpg/**",
                        "/token/refresh/**",
                        "/register/**",
                        "/pk/start/game/**",
                        "/move/bot/**"
                ).permitAll()//放行验证码和token刷新控制器
                 .mvcMatchers("/get/users/**",
                         "/update/enabled",
                         "/ucenter/count",
                         "/essays/**",
                         "/delete/essay/acl",
                         "/essay").hasIpAddress("10.13.99.242")
                .and()
                .authorizeRequests().//开启请求认证
                 anyRequest().authenticated()//除上面两个请求任何请求都要认证
                .and()
                .formLogin()//开启表单验证
                .and()
                .cors()
                .configurationSource(configurationSource())
                .and()
                .csrf().disable();//关闭跨域请求保护
        CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(redisOperator);//导入redis工具类
        customAuthenticationFilter.setAuthenticationManager(authenticationManager());//设置权限控制器
        customAuthenticationFilter.setFilterProcessesUrl("/login");//指定处理登录请求url
        http.addFilterBefore(customAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);//将自己写过滤器放UsernamePasswordFilter前面
        http.addFilterAt(new CustomAuthorizationFilter(),UsernamePasswordAuthenticationFilter.class);//替换UsernamePasswordFilter
    }

    CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/websocket/**");
    }
}